<?php
namespace app\middleware;

use app\exception\ApiException;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;

class SignMiddleware implements MiddlewareInterface
{
    protected $sign_key = '';

    public function process(Request $request, callable $handler) : Response
    {
        $this->sign_key = env('SIGN_KEY');
        $this->check($request);
        $response = $handler($request); // 继续向洋葱芯穿越，直至执行控制器得到响应

        return $response;
    }

    protected function check($request){
        $params = $request->all();
        $sign = $this->sign($params);
        if((!isset($params['sign']) || $sign['after']!=$params['sign'])){
            $debug = env('APP_ENV')!='production' ? $sign['before'] : '';
            throw new ApiException('sign error:'.$debug);
        }
    }
    protected function defaultParam($data){
        $data['time'] = time();
        $data['sign'] = $this->sign($data);
        return $data;
    }

    protected function sign($data, $sign_key = '')
    {
        $sign_key = $sign_key ?: $this->sign_key;
        unset($data['sign']);

        $signStr = $this->beforeSignStr($data);
        $signStr = trim($signStr,'|');
        $signStr .= '|'.$sign_key;
        return ['after'=>md5($signStr),'before'=>$signStr];
        return md5($signStr);
    }

    protected function beforeSignStr($data,$k=''){
        $signStr = '';
        ksort($data);


        foreach ($data as $key => $value) {
            if(is_array($value)){
                //$value = $this->beforeSignStr($value,$key);
                //$signStr .=$value;
                $value = json_encode($value);
                $signStr .= ($k ? ($k.'['.$key .']') : $key). "=" . $value . "|";
            }else{
                //$value = rawurlencode($value);//sdk 前面不需要 urlencode
                $signStr .= ($k ? ($k.'['.$key .']') : $key). "=" . $value . "|";
            }

        }
        return $signStr;
    }
}